/******************************************************************************
 Copyright (c) 2021-2022 Qualcomm Technologies International, Ltd.
 All Rights Reserved.
 Qualcomm Technologies International, Ltd. Confidential and Proprietary.

 REVISION:      $Revision: #9 $
******************************************************************************/
#include "cap_client_util.h"
#include "cap_client_common.h"
#include "cap_client_init_stream_and_control_req.h"
#include "cap_client_remove_device_req.h"
#include "cap_client_vcp_operation_req.h"
#include "cap_client_debug.h"
#include "cap_client_csip_handler.h"
#include "cap_client_vcp_handler.h"


void capClientSetAbsoluteVolumeReq(CsrCmnListElm_t *elem,
                             uint8 volumeSetting, 
                             CAP_INST *inst,
                             CapClientGroupInstance *cap)
{
    VcpInstElement* vcp = (VcpInstElement*)elem;

    CAP_CLIENT_INFO("\n(CAP) : capClientSetAbsoluteVolumeReq \n");

    for (; vcp; vcp = vcp->next)
    {
        if (vcp->recentStatus == CAP_CLIENT_RESULT_SUCCESS)
        {
            inst->vcpRequestCount++;
            VcpAbsoluteVolumeRequest(vcp->vcpHandle, volumeSetting);
        }
        else
        {
            CAP_CLIENT_INFO("\n(CAP) capClientSetAbsoluteVolumeReq : Recent Error \n"); 
        }

    }

    if (inst->vcpRequestCount == 0)
    {
        elem = (CsrCmnListElm_t*)(cap->vcpList.first);

        capClientSendChangeVolumeCfm(inst->profileTask, 
                                     inst->activeGroupId, 
                                     CAP_CLIENT_RESULT_SUCCESS,
                                     inst->deviceCount,
                                     (VcpInstElement*)elem,
                                     inst);
    }
    
}

void capClientSetVcpMuteStateReq(VcpInstElement* vcp,
                                 bool mute,
                                 CAP_INST *inst,
                                 CapClientGroupInstance *cap)
{
    VcpInstElement *tmp = vcp;
    CAP_CLIENT_INFO("\n(CAP) : capClientSetVcpMuteStateReq \n");

    for (; vcp; vcp = vcp->next)
    {
        if (vcp->recentStatus == CAP_CLIENT_RESULT_SUCCESS)
        {
            inst->vcpRequestCount++;
            mute ? VcpMuteRequest(vcp->vcpHandle) : VcpUnmuteRequest(vcp->vcpHandle);
        }
        else
        {
            CAP_CLIENT_INFO("\n(CAP) capClientSetVcpMuteStateReq : Recent Error \n");
        }
    }

    if (inst->vcpRequestCount == 0)
    {
        tmp = (VcpInstElement*)cap->vcpList.first;
        capClientSendMuteCfm(inst->vcpProfileTask, cap->groupId, CAP_CLIENT_RESULT_SUCCESS,inst->deviceCount, tmp, inst);

    }
}

static void capClientHandleVcpInitCfm(const Msg msg, CAP_INST *inst, CapClientGroupInstance *gInst)
{
    VcpInitCfm *cfm = (VcpInitCfm*)msg;

    VcpInstElement *vcp = (VcpInstElement*)
                        CAP_CLIENT_GET_VCP_ELEM_FROM_CID(gInst->vcpList, cfm->cid);


    CAP_CLIENT_INFO("\n(CAP) : capClientHandleVcpInitCfm: VcpInitCfm: \n");
    CAP_CLIENT_INFO("(CAP) :  Status : 0x%02x, Vcp Handle: 0x%04x, BtConnId: 0x%04x \n", cfm->status, cfm->prflHndl, cfm->cid);

    /* If no VCP found corresponding to cid
     * PANIC since the VCP instance would already be added
     * in INIT cfm for given CID*/

    if(vcp == NULL)
    {
        CAP_CLIENT_ERROR("\n(CAP) capClientHandleVcpInitCfm: PANIC unable to find the VCP instance ");
        return;
    }

    vcp->recentStatus = capClientGetCapClientResult(cfm->status, CAP_CLIENT_VCP);

    if(cfm->status == VCP_STATUS_SUCCESS)
        vcp->vcpHandle = cfm->prflHndl;

    if(cfm->status != VCP_STATUS_IN_PROGRESS)
        inst->vcpRequestCount--;

    /* All the Init Cfms are recieved and counter Hits zero */
    if(inst->vcpRequestCount == 0)
    {
        CsrCmnListElm_t *elem = (CsrCmnListElm_t*)((&gInst->vcpList)->first);
        /* If Role is Commander Then Intialize VCP as well */

        gInst->capState = CAP_CLIENT_STATE_INIT_STREAM_CTRL;

        capClientSendStreamControlInitCfm(inst->appTask,
                                         inst->deviceCount,
                                         inst->activeGroupId,
                                         TRUE,
                                         CAP_CLIENT_RESULT_SUCCESS,
                                         gInst->role,
                                         elem);
        /* Enable CSIP/VCP ccid*/
        capClientCsipEnableCcd(inst, TRUE);
        capClientVcpEnableCcd(inst, TRUE);
    }
}

void capClientHandleVolumeStateInd(VcpVolumeStateInd *ind,
    CAP_INST* inst, CapClientGroupInstance* gInst)
{
    MAKE_CAP_CLIENT_MESSAGE(CapClientVolumeStateInd);

    VcpInstElement* vcp = (VcpInstElement*)
        CAP_CLIENT_GET_VCP_ELEM_FROM_PHANDLE(gInst->vcpList, ind->prflHndl);

    vcp->volumeState = ind->volumeState;
    vcp->muteState = ind->mute;

    CAP_CLIENT_INFO("(CAP) : Vcp Handle: 0x%04x, VolumeState : 0x%02x, Mute: 0x%02x \n", ind->prflHndl,ind->volumeState, ind->mute);

    /* Send Volume State Indication to application */
    message->groupId = inst->activeGroupId;
    message->volumeState = vcp->volumeState;
    message->mute = vcp->muteState;
    message->changeCounter = ind->changeCounter;

    CapClientMessageSend(inst->profileTask, CAP_CLIENT_VOLUME_STATE_IND, message);

}

void capClientHandleAbsVolCfm(const Msg msg, CAP_INST* inst, CapClientGroupInstance* gInst)
{
    VcpAbsVolCfm* cfm = (VcpAbsVolCfm*)msg;

    VcpInstElement* vcp = (VcpInstElement*)
                       CAP_CLIENT_GET_VCP_ELEM_FROM_PHANDLE(gInst->vcpList, cfm->prflHndl);

    CAP_CLIENT_INFO("\n(CAP) : capClientHandleAbsVolCfm: vcpRequestCount:  %d\n", inst->vcpRequestCount);
    inst->vcpRequestCount--;

    if (vcp == NULL)
    {
        capClientSendChangeVolumeCfm(inst->vcpProfileTask, gInst->groupId, CAP_CLIENT_RESULT_FAILURE_UNKNOWN_ERR,
                               0, NULL, inst);
        CAP_CLIENT_ERROR("\n(CAP) capClientHandleAbsVolCfm: PANIC unable to find the VCP instance");
        return;
    }

    vcp->recentStatus = capClientGetCapClientResult(cfm->status, CAP_CLIENT_VCP);

    if (inst->vcpRequestCount == 0)
    {
        CsipInstElement* csip = (CsipInstElement*)gInst->csipList.first;
        vcp = (VcpInstElement*)(gInst->vcpList.first);

        if (capClientIsGroupCoordinatedSet(gInst))
        {
            /* If the CSIP is in Locked state and pending operation is not clear
             * then there is procedure which is already running hence just send
             * Cfm */

            if (csip->lock == CAP_CLIENT_LOCK_STATE_ENABLED
                  && gInst->pendingOp == CAP_CLIENT_OP_NONE)
            {
                gInst->pendingOp = CAP_CLIENT_VCP_SET_VOL;
                capClientSetCsisLockState(csip, &inst->csipRequestCount, FALSE);
            }
            else
            {
                capClientSendChangeVolumeCfm(inst->vcpProfileTask,
                    gInst->groupId,
                    CAP_CLIENT_RESULT_SUCCESS,
                    inst->deviceCount,
                    vcp,
                    inst);
            }
        }
        else
        {
            capClientSendChangeVolumeCfm(inst->vcpProfileTask,
                gInst->groupId,
                CAP_CLIENT_RESULT_SUCCESS,
                inst->deviceCount,
                vcp, inst);
        }
    }
}

void capClientHandleUnMuteCfm(const Msg msg, CAP_INST* inst, CapClientGroupInstance* gInst)
{
    VcpUnmuteCfm* cfm = (VcpUnmuteCfm*)msg;
    VcpInstElement* vcp = (VcpInstElement*)
          CAP_CLIENT_GET_VCP_ELEM_FROM_PHANDLE(gInst->vcpList, cfm->prflHndl);


    CAP_CLIENT_INFO("\n(CAP) : capClientHandleUnMuteCfm: VcpAbsVolCfm: \n");


    if (vcp == NULL)
    {
        CAP_CLIENT_ERROR("\n(CAP) capClientHandleUnMuteCfm: PANIC unable to find the VCP instance ");
        return;
    }

    vcp->recentStatus = capClientGetCapClientResult(cfm->status, CAP_CLIENT_VCP);
    inst->vcpRequestCount--;

    if (inst->vcpRequestCount == 0)
    {
        CsipInstElement* csip = (CsipInstElement*)gInst->csipList.first;
        vcp = (VcpInstElement*)(gInst->vcpList.first);

        if (capClientIsGroupCoordinatedSet(gInst))
        {
            /* If the CSIP is in Locked state and pending operation is not clear
             * then there is procedure which is already running hence just send 
             * Cfm */

            if (csip->lock == CAP_CLIENT_LOCK_STATE_ENABLED
                && gInst->pendingOp == CAP_CLIENT_OP_NONE)
            {
                gInst->pendingOp = CAP_CLIENT_VCP_MUTE;
                capClientSetCsisLockState(csip, &inst->csipRequestCount, FALSE);
            }
            else
            {
                capClientSendMuteCfm(inst->vcpProfileTask,
                                     gInst->groupId,
                                     CAP_CLIENT_RESULT_SUCCESS,
                                     inst->deviceCount,
                                     vcp,
									 inst);
            }
        }
        else
        {

            capClientSendMuteCfm(inst->vcpProfileTask,
                                 gInst->groupId,
                                 CAP_CLIENT_RESULT_SUCCESS,
                                 inst->deviceCount,
                                 vcp, 
								 inst);
        }

    }
}

void capClientHandleMuteCfm(const Msg msg, CAP_INST* inst, CapClientGroupInstance* gInst)
{
    VcpMuteCfm* cfm = (VcpMuteCfm*)msg;
    VcpInstElement* vcp = (VcpInstElement*)
                    CAP_CLIENT_GET_VCP_ELEM_FROM_PHANDLE(gInst->vcpList, cfm->prflHndl);


    CAP_CLIENT_INFO("\n(CAP) : capClientHandleMuteCfm: VcpAbsVolCfm: \n");


    if (vcp == NULL)
    {
        CAP_CLIENT_ERROR("\n(CAP) capClientHandleMuteCfm: PANIC unable to find the VCP instance ");
        return;
    }

    vcp->recentStatus = capClientGetCapClientResult(cfm->status, CAP_CLIENT_VCP);
    inst->vcpRequestCount--;

    if (inst->vcpRequestCount == 0)
    {
        CsipInstElement* csip = (CsipInstElement*)gInst->csipList.first;
        vcp = (VcpInstElement*)(gInst->vcpList.first);

        if (capClientIsGroupCoordinatedSet(gInst))
        {
            if (csip->lock == CAP_CLIENT_LOCK_STATE_ENABLED)
            {
                gInst->pendingOp = CAP_CLIENT_VCP_MUTE;
                capClientSetCsisLockState(csip, &inst->csipRequestCount, FALSE);
            }
            else
            {
                capClientSendMuteCfm(inst->vcpProfileTask,
                                     gInst->groupId,
                                     CAP_CLIENT_RESULT_SUCCESS,
                                     inst->deviceCount,
                                     vcp,
								     inst);
            }
        }
        else
        {

            capClientSendMuteCfm(inst->vcpProfileTask,
                                 gInst->groupId,
                                 CAP_CLIENT_RESULT_SUCCESS,
                                 inst->deviceCount,
                                 vcp,
								 inst);
        }
    }
}


void capClientHandleVcpMsg(CAP_INST *inst, const Msg msg)
{
    CsrBtGattPrim *prim = (CsrBtGattPrim *)msg;

    CapClientGroupInstance *gInst =
               (CapClientGroupInstance*)CAP_CLIENT_GET_GROUP_INST_DATA(inst->activeGroupId);

    if (gInst == NULL)
    {
        CAP_CLIENT_INFO("capClientHandleVcpMsg: gInst is NULL");
        return;
    }

    switch(*prim)
    {
        case VCP_INIT_CFM:
        {
            gInst->pendingOp = CAP_CLIENT_VCP_INIT;
            capClientHandleVcpInitCfm(msg, inst, gInst);
        }
        break;

        case VCP_VCS_TERMINATE_CFM:
        {
            capClientRemoveGroup(msg, inst, CAP_CLIENT_VCP);
        }
        break;

        case VCP_ABS_VOL_CFM:
        {
            capClientHandleAbsVolCfm(msg, inst, gInst);
        }
        break;

        case VCP_MUTE_CFM:
        {
            capClientHandleMuteCfm(msg, inst, gInst);
        }
        break;
        case VCP_UNMUTE_CFM:
        {
            capClientHandleUnMuteCfm(msg, inst, gInst);
        }
        break;

        case VCP_DESTROY_CFM:
        {
            VcpDestroyCfm *cfm = (VcpDestroyCfm*)msg;

            if(cfm->status == VCP_STATUS_SUCCESS)
            {
                capClientRemoveGroup(NULL, inst, CAP_CLIENT_VCP);
            }
        }
        break;

        case VCP_READ_VOLUME_STATE_CFM:
        {
            CapClientResult result;
            VcpReadVolumeStateCfm* cfm = (VcpReadVolumeStateCfm*)msg;
            VcpInstElement* vcp = (VcpInstElement*)
                CAP_CLIENT_GET_VCP_ELEM_FROM_PHANDLE(gInst->vcpList, cfm->prflHndl);

            vcp->muteState = cfm->mute;
            vcp->volumeState = cfm->volumeSetting;
            result = capClientGetCapClientResult(cfm->status, CAP_CLIENT_VCP);

            /* Decerement the VCP Operation Counter on Cfm*/
            inst->vcpRequestCount--;

            capCLientSendReadVolumeStateCfm(inst->vcpProfileTask,
                                           inst->activeGroupId,
                                           result, vcp, cfm->mute,
                                           cfm->volumeSetting,
                                           cfm->changeCounter);
        }
        break;

        case VCP_READ_VOLUME_FLAG_CFM:
        {
            VcpReadVolumeFlagCfm* cfm = (VcpReadVolumeFlagCfm*)msg;
            VcpInstElement* vcp = (VcpInstElement*)
                CAP_CLIENT_GET_VCP_ELEM_FROM_PHANDLE(gInst->vcpList, cfm->prflHndl);

            vcp->flags = cfm->volumeFlag;
        }
        break;

        case VCP_VOLUME_STATE_IND:
        {
            VcpVolumeStateInd* ind = (VcpVolumeStateInd*)msg;
            capClientHandleVolumeStateInd(ind, inst, gInst);
        }
        break;

        case VCP_VOLUME_FLAG_IND:
        {
            VcpVolumeFlagInd* ind = (VcpVolumeFlagInd*)msg;
            VcpInstElement* vcp = (VcpInstElement*)
                CAP_CLIENT_GET_VCP_ELEM_FROM_PHANDLE(gInst->vcpList, ind->prflHndl);

            vcp->flags = ind->volumeFlag;
        }
        break;

        case VCP_VOLUME_STATE_SET_NTF_CFM:
        {
            VcpVolumeStateSetNtfCfm* cfm = (VcpVolumeStateSetNtfCfm*)msg;
            CSR_UNUSED(cfm);
        }
        break;

        case VCP_VOLUME_FLAG_SET_NTF_CFM:
        {
            VcpVolumeFlagSetNtfCfm* cfm = (VcpVolumeFlagSetNtfCfm*)msg;
            CSR_UNUSED(cfm);
        }
        break;

        default:
            break;
    }
}

/* This is utility function for enabling/disabling VCP CCD  */
void capClientVcpEnableCcd(CAP_INST *inst, uint8 enable)
{
    CapClientGroupInstance* cap = CAP_CLIENT_GET_GROUP_INST_DATA(inst->activeGroupId);
    VcpInstElement* vcp = NULL;

    if (cap)
    {
        vcp = (VcpInstElement*)cap->vcpList.first;
    }

    while (vcp)
    {
        CAP_CLIENT_INFO("\n(CAP) : capClientVcpEnableCcd CsipCSRegisterForLockNotificationReq\n");
        VcpVolumeStateRegisterForNotificationReq(vcp->vcpHandle, enable);
        VcpVolumeFlagRegisterForNotificationReq(vcp->vcpHandle, enable);
        vcp = vcp->next;
    }
}
